package com.cloud.pole.weixin.controller;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.cloud.pole.common.constant.CommonConstants;
import com.cloud.pole.common.exception.BaseException;
import com.cloud.pole.common.exception.ParamException;
import com.cloud.pole.common.msg.ApiRestResponse;
import com.cloud.pole.common.util.RegexUtils;
import com.cloud.pole.common.util.security.MD5SignUtils;
import com.cloud.pole.weixin.biz.WxAppBiz;
import com.cloud.pole.weixin.biz.WxPayJoinBiz;
import com.cloud.pole.weixin.model.entity.WxApp;
import com.cloud.pole.weixin.model.entity.WxPayJoin;
import com.cloud.pole.weixin.service.WxPayNotifyService;
import com.cloud.pole.weixin.service.WxPayService;
import com.cloud.pole.weixin.util.wechat.CommonRequest;
import com.cloud.pole.weixin.util.wechat.GetWxOrderno;
import com.cloud.pole.weixin.util.wechat.PayCommonUtil;

import lombok.extern.slf4j.Slf4j;

/*
*2019年4月30日
*cloud-weixin
*author:frank-chen
*/
@Controller
@RequestMapping("wxPay/front")
@Slf4j
public class WxPayController {

	@Autowired 
	private WxPayService wxPayService;
	@Autowired 
	private WxPayJoinBiz wxPayJoinBiz;
	@Autowired 
	private WxAppBiz wxAppBiz;
	@Autowired 
	private WxPayNotifyService wxPayNotifyService;
	
	@ResponseBody
    @RequestMapping(value = "/unifiedOrder")
    public ApiRestResponse<String> unifiedOrder(
    		@RequestParam(name="payJoinId", defaultValue = "") String payJoinId,
    		@RequestParam(name="outTradeNo", defaultValue = "") String outTradeNo,
    		@RequestParam(name="totalFee", defaultValue = "") String totalFee,
    		@RequestParam(name="openId", defaultValue = "") String openId,
    		@RequestParam(name="redirectUri", defaultValue = "") String callBackUri){   	
    	try {
    		ParamException.err(StringUtils.isBlank(payJoinId), "payJoinId不能为空");
			ParamException.err(StringUtils.isBlank(outTradeNo), "outTradeNo不能为空");
			ParamException.err(StringUtils.isBlank(totalFee), "totalFee不能为空");
			ParamException.err(StringUtils.isBlank(openId), "openId不能为空");
			ParamException.err(StringUtils.isBlank(callBackUri), "callBackUri不能为空");
			ParamException.err(!RegexUtils.isPositiveInteger(payJoinId), "payJoinId错误");			
			ParamException.err(!RegexUtils.isPositiveInteger(totalFee), "totalFee错误");					
			String strResponseMsg = wxPayService.unifiedOrderJsApi(Integer.parseInt(payJoinId), outTradeNo, Long.parseLong(totalFee), openId, callBackUri);
			return ApiRestResponse.success(CommonConstants.STATUS_OK_MESSAGE, strResponseMsg);
    	} catch (BaseException e) {
			return ApiRestResponse.fail(e.getStatus(), e.getMessage(), null);
		} catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			return ApiRestResponse.fail(CommonConstants.STATUS_ERROR_MESSAGE, null);
		}
    }
	
	@ResponseBody
    @RequestMapping(value = "/payWxNotify")
	public void payWxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
		try {
			// 读取参数
			InputStream inputStream;
			StringBuffer sb = new StringBuffer();
			inputStream = request.getInputStream();
			String s;
			BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
			while ((s = in.readLine()) != null) {
				sb.append(s);
			}
			in.close();
			inputStream.close();
			log.info("获取状态返回：" + sb.toString());
			
			// 解析xml成map
			Map<String, String> map = new HashMap<String, String>();
			map = GetWxOrderno.doXMLParse(sb.toString());
			String appid = (String) map.get("appid");
			WxApp wxApp = wxAppBiz.selectByAppId(appid);
			if(wxApp == null) {
				log.error("获取wxApp失败：appid-" + appid);
				return;
			}
			// 过滤空 设置 TreeMap
			SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
			Iterator it = map.keySet().iterator();
			while (it.hasNext()) {
				String parameter = (String) it.next();
				String parameterValue = map.get(parameter);

				String v = "";
				if (null != parameterValue) {
					v = parameterValue.trim();
				}
				packageParams.put(parameter, v);
			}
			// 账号信息
			String key = wxApp.getPayKey(); // key
			String outTradeNo = null;
			boolean isSendNotifyMsg = false;
			// 判断签名是否正确
			if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {		
				log.info(packageParams.toString() );
				
				String resXml = "";
				if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
					log.info("支付成功");
					// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
					resXml = "<xml>"
							+ "<return_code><![CDATA[SUCCESS]]></return_code>"
							+ "<return_msg><![CDATA[OK]]></return_msg>" 
							+ "</xml>";
					isSendNotifyMsg = true;
				} 
				else {
					log.error("支付失败,错误信息：" + packageParams.get("err_code"));
					resXml = "<xml>"
							+ "<return_code><![CDATA[FAIL]]></return_code>"
							+ "<return_msg><![CDATA[blank msg]]></return_msg>"
							+ "</xml>";
				}
				BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
				out.write(resXml.getBytes());
				out.flush();
				out.close();
				wxPayNotifyService.payWxNotify(packageParams);

				//转发业务接口
				String attach = (String) packageParams.get("attach");
				String transactionId = (String) packageParams.get("transaction_id");
				String pgOrderSn = (String) packageParams.get("out_trade_no");
				if(!StringUtils.isEmpty(attach)) {
					String joinAppId = attach;
					log.info("joinAppId-" + joinAppId);
					WxPayJoin wxPayJoin = wxPayJoinBiz.selectByPrimaryKey(Integer.parseInt(joinAppId));
					if(wxPayJoin != null && !StringUtils.isEmpty(wxPayJoin.getCallBackUrl())) {
						String nonceStr = Long.toString(System.currentTimeMillis());
						SortedMap<String, String> params = new TreeMap<String, String>();
						params.put("pgOrderSn", pgOrderSn);
						params.put("nonceStr", nonceStr);
						params.put("transactionId", transactionId);
						params.put("joinAppId", joinAppId);
						String strSign = MD5SignUtils.createMD5Sign(params, "UTF-8");
						log.info("callBackUrl -" + wxPayJoin.getCallBackUrl() );
						String callBackUrl = wxPayJoin.getCallBackUrl() + "?joinAppId=" + joinAppId + "&pgOrderSn=" + pgOrderSn + 
												"&transactionId="  + transactionId + "&sign=" + strSign + "&nonceStr=" +nonceStr;
						String strResponse = CommonRequest.doGet(callBackUrl);
						log.info("callResponse -" + strResponse);
					}
				}	
			} else {
				log.error("通知签名验证失败");
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}
}
